# -*- encoding: utf-8 -*-
"""
@Project : AIGateWay 
@FileName: async_handler
@Time    : 2020/11/26 14:59
@Author  : chenych
@Desc    :
"""

from Client.safe_request import SafeRequest
from Core import  SYS_CODE
import json
import ailog
import time
from Core import conf
from Core import create_face_loop,create_index_loop
from util.image_util import image_pos,image_area,base64toarray
import  threading


class MyThread(threading.Thread):
    def __init__(self, func, args, name=''):
        threading.Thread.__init__(self)
        self.name = name
        self.func = func
        self.args = args
        self.result = self.func(*self.args)

    def get_result(self):
        try:
            return self.result
        except Exception:
            return None



class StrangeRecogTask():

    host = conf.get('face_ability_url', 'host_face')
    port = conf.get('face_ability_url', 'port_face')
    url_image = 'http://{}:{}{}'.format(host, port, conf.get('face_ability_url','url_image'))
    url_index_search = 'http://{}:{}{}'.format(host, port, conf.get('face_ability_url','url_index_search_base'))
    url_index_create = 'http://{}:{}{}'.format(host, port, conf.get('face_ability_url','url_index_create'))
    url_face_create = 'http://{}:{}{}'.format(host, port, conf.get('face_ability_url','url_face_create_base'))
    url_face_search = 'http://{}:{}{}'.format(host, port, conf.get('face_ability_url','url_face_search'))

    scoreThreshold = 0.4
    score = 0

    area_score = 3600
    area_pos_score = 0.3
    area_drop = 0.2

    face_quality_score = 60


    FACE_QUALITY = 1
    FACE_MORE = 2
    FACE_POS = 3
    FACE_AREA = 4
    NO_FACE= 5
    FACE_NO_MATCH = 6

    FACE_MSG_DICT = {
        FACE_QUALITY:'人脸质量评分低',
        FACE_MORE:'检测多个人脸',
        FACE_POS:'人脸位置不合格',
        FACE_AREA:'人脸大小不合格',
        NO_FACE:'未检测到人脸',
        FACE_NO_MATCH:'没有符合条件的人脸'

    }



    httpclient = SafeRequest()

    @staticmethod
    def __build_resp(seqid, code, message, flag, data):

        resp_dict = {

            'seqid': seqid,
            'code': code,
            'message': message,
            'flag': flag,
            'data': data
        }

        return resp_dict


    @classmethod
    def __get_featrue(cls,imageBase64s):

        data = {
            'image_base64': imageBase64s
        }
        header = {'Content-type': 'application/json'}

        res_feature = cls.httpclient.post(url=cls.url_image, body=json.dumps(data))

        res_feature = json.loads(res_feature)
        return res_feature


    @classmethod
    def __search_index(cls,deviceId):


        data = {
            'group_id': deviceId
        }
        header = {'Content-type': 'application/json'}

        res_index_search =  cls.httpclient.post(url=cls.url_index_search, body=json.dumps(data))

        ailog.debug(res_index_search)


        return res_index_search



    @classmethod
    def __create_index(cls,deviceId):

        data = {
            'group_id': deviceId
        }
        header = {'Content-type': 'application/json'}

        res_index_create =  cls.httpclient.post(url=cls.url_index_create,body=json.dumps(data))


        res_index_create = json.loads(res_index_create)
        ailog.debug(res_index_create)
        return res_index_create


    @classmethod
    def __create_face(cls,deviceId,visitorId,featureData):

        data = {
            'ext_id':visitorId,
            'feature_data':featureData,
            'group_id':deviceId
        }


        header = {'Content-type': 'application/json'}

        res_face_create =  cls.httpclient.post(url=cls.url_face_create,body=json.dumps(data))

        res_face_create = json.loads(res_face_create)

        return res_face_create


    @classmethod
    def __search_face(cls,indexNames,featureData,scoreThreshold):


        data = {
            'group_id':indexNames,
            'feature_data':featureData,
            'threshold':scoreThreshold,
            'top_n':3
        }
        header = {'Content-type': 'application/json'}

        res = cls.httpclient.post(url=cls.url_face_search,body=json.dumps(data))
        res = json.loads(res)
        return res

    @classmethod
    def check_face_result(cls,imageBase64s,feature):

        position = feature['bounding_box']
        position = {
            'left':position[0],
            'top': position[1],
            'width': position[2],
            'height': position[3]
        }

        faceQuality  =feature['score']

        img_array = base64toarray(imageBase64s)

        all_h, all_w, _ = img_array.shape
        #all_h = 360
        #all_w = 640

        # if faceQuality<cls.face_quality_score:
        #
        #     msg = cls.FACE_MSG_DICT.get(cls.FACE_QUALITY,'')
        #     return False,msg+str(faceQuality)

        # if image_area(position['width'],position['height'])<cls.FACE_AREA:
        #     msg = cls.FACE_MSG_DICT.get(cls.FACE_AREA, '')
        #     return False, msg+str(image_area(position['width'],position['height']))

        # pos_score =  image_pos(fea_x1=position['left'],fea_y1=(all_h-position['top']),fea_h=position['height'],fea_w=position['width'],
        #              all_w=all_w,all_h=all_h,drop=cls.area_drop)
        # if pos_score<cls.area_pos_score:
        #
        #     msg = cls.FACE_MSG_DICT.get(cls.FACE_POS, '')
        #     return False, msg+str(pos_score)

        return True,'检测通过'


    @classmethod
    def run(cls, seqid, deviceId, visitorId, imageBase64s_list):

        start_time =time.time()



        try:

            # 查库
            res_search_index = cls.__search_index(deviceId=deviceId)
            INDEX_EXIT = True if 'group_id' in res_search_index else False
            ailog.info('Index is exit : {}'.format(INDEX_EXIT))



            #获取特征
            #多个图片抽特征
            feature_list = []
            res_feature = []




            #多线程判断图片
            def loop_feature_search(imgbase64,groupid):

                res_f = cls.__get_featrue(imgbase64)

                if 'faces' not in res_f:
                    return None, None


                feature_list = res_f['faces']
                for feature_dict in feature_list:

                    res_search_face = cls.__search_face(indexNames=groupid,
                                                        featureData=feature_dict['feature_Data'],
                                                        scoreThreshold=cls.scoreThreshold)

                    if len(res_search_face['faces']) >= 1:
                        face_data = res_search_face['faces'][0]

                        #匹配上人脸
                        if face_data['score'] > cls.score:
                            visitorId = face_data['face_id']
                            #ailog.info('FACE_MATCH : {}'.format(visitorId))

                            data = {
                                'visitorId': visitorId,
                                'timeSecond': time.time() - start_time
                            }

                            resp_dict = cls.__build_resp(seqid=seqid,
                                                         code=SYS_CODE.RESPCODE.SUCCESS,
                                                         message=SYS_CODE.RESPCODE.get_msg(SYS_CODE.RESPCODE.SUCCESS),
                                                         flag=SYS_CODE.RESPCODE.FLAG_SUCCESS,
                                                         data=data)

                            return res_f,resp_dict

                return res_f,None




            def loop_feature_without_search(imgbase64):

                res_f = cls.__get_featrue(imgbase64)

                if 'faces' not in res_f:
                    return None, None

                return res_f,None


            threads = []

            for imageBase64s in imageBase64s_list:

                if INDEX_EXIT:
                    t = MyThread(loop_feature_search, (imageBase64s,deviceId), loop_feature_search.__name__)
                else:
                    t = MyThread(loop_feature_without_search, (imageBase64s,), loop_feature_without_search.__name__)

                threads.append(t)

            for i in range(len(threads)):  # start threads 此处并不会执行线程，而是将任务分发到每个线程，同步线程。等同步完成后再开始执行start方法
                threads[i].start()
            for i in range(len(threads)):  # jion()方法等待线程完成
                threads[i].join()

            for i in range(len(threads)):  # get_result()方法等待线程

                res_f , result = threads[i].get_result()

                if result is not None:

                    ailog.info('MATCH ..')
                    #人脸匹配到结果返回
                    return result

                if res_f is None:
                    continue

                feature_list += res_f['faces']
                res_feature.append(res_f)



            #判断没有人脸
            if len(feature_list)==0:

                data = {
                    'visitorId': '',
                    'timeSecond': time.time() - start_time
                }
                ailog.info('{} : {}'.format(cls.FACE_MSG_DICT.get(cls.NO_FACE, ''), res_feature))
                resp_dict = cls.__build_resp(seqid=seqid,
                                             code=SYS_CODE.STATUS.SUCCESS,
                                             message=cls.FACE_MSG_DICT.get(cls.NO_FACE,''),
                                             flag=SYS_CODE.RESPCODE.FLAG_FAIL,
                                             data=data)

                return resp_dict




            #==============未匹配到================
            ailog.info('FACE NOT MATCH...')


            for imageBase64s,res_f in zip(imageBase64s_list,res_feature):

                feature_list = res_f['faces']
                orgin_feature_list_copy = feature_list
                feature_list = []
                for f_dict in orgin_feature_list_copy:
                    FEATURE_CHECK,CHECK_MSG = cls.check_face_result(imageBase64s,f_dict)
                    #符合条件
                    if FEATURE_CHECK:
                        feature_list.append(f_dict)

                #####符合入库 条件


                # 没有符合人脸
                if len(feature_list) == 0:
                    data = {
                        'visitorId': '',
                        'timeSecond': time.time() - start_time
                    }
                    continue



                #多个人脸未匹配上
                if len(feature_list) >1:

                    data = {
                        'visitorId': '',
                        'timeSecond': time.time() - start_time
                    }
                    ailog.info('{} : {}'.format('多个人脸未匹配上', res_feature))
                    continue


                #单人脸未匹配
                if len(feature_list)==1:


                    ailog.info('{} : {}'.format('单人脸未匹配', res_feature))

                    feature_dict = feature_list[0]

                    FEATURE_CHECK,CHECK_MSG = cls.check_face_result(imageBase64s,feature_dict)

                    #未合格
                    if not FEATURE_CHECK:

                        data = {
                            'visitorId': '',
                            'timeSecond': time.time() - start_time
                        }

                        ailog.info('{} : {}'.format(FEATURE_CHECK,CHECK_MSG))

                        continue


                    #合格
                    else:

                        #没库
                        if not INDEX_EXIT:

                            ailog.info('创建库。')


                            res_create_index =  cls.__create_index(deviceId=deviceId)
                            res_create_face =  cls.__create_face(deviceId=deviceId,
                                                                      visitorId=visitorId,
                                                                      featureData=feature_dict['feature_Data'])


                            
                        #有库
                        else:

                            ailog.info('创建档案。')

                            cls.__create_face(deviceId=deviceId,
                                               visitorId=visitorId,
                                               featureData=feature_dict['feature_Data'])




                        data = {
                            'visitorId': visitorId,
                            'timeSecond': time.time() - start_time
                        }

                        resp_dict = cls.__build_resp(seqid=seqid,
                                                     code=SYS_CODE.RESPCODE.SUCCESS,
                                                     message=SYS_CODE.RESPCODE.get_msg(SYS_CODE.RESPCODE.SUCCESS),
                                                     flag=SYS_CODE.RESPCODE.FLAG_SUCCESS,
                                                     data=data)

                        return resp_dict



            data = {
                'visitorId':'',
                'timeSecond':time.time()-start_time
            }
            ailog.info('NOT MATCH RULE')

            resp_dict = cls.__build_resp(seqid=seqid,
                                         code=SYS_CODE.RESPCODE.FAIL,
                                         message='NOT MATCH RULE',
                                         flag=SYS_CODE.RESPCODE.FLAG_SUCCESS,
                                         data=data)

            return resp_dict



        except Exception as e:

            ailog.error('error : {}'.format(e))

            resp_dict = cls.__build_resp(seqid=seqid,
                                         code=SYS_CODE.RESPCODE.FAIL,
                                         message=SYS_CODE.RESPCODE.get_msg(SYS_CODE.RESPCODE.FAIL),
                                         flag=SYS_CODE.RESPCODE.FLAG_FAIL,
                                         data={})

            return resp_dict






























